<?php
// +----------------------------------------------------------------------
// | ZGUAN [ 致力于帮助更多的中小账单物联网转型 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2024 https://www.zguan.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ZGUAN 并不是自由软件，未经许可不能去掉ZGUAN 相关版权
// +----------------------------------------------------------------------
// | Author: ZGUAN Team <admin@zguan.cn>  0769-82282996  15899929162
// +----------------------------------------------------------------------
namespace app\controller\property\bill;

use think\App;
use app\controller\property\Base;
use app\common\services\CacheService;
use app\validate\bill\BillCatalogValidate;
use app\common\repositories\bill\BillCateRepository;
use app\common\repositories\bill\BillBasicRepository;
use app\common\repositories\bill\BillCatalogRepository;
use app\common\repositories\energy\EnergyPlanRepository;
use app\common\repositories\energy\EnergyMeterRepository;
use app\common\repositories\property\basic\PropertyBasicRepository;


class BillCatalog extends Base
{

    protected $repository;

    public function __construct(App $app, BillCatalogRepository $repository)
    {
        parent::__construct($app);

        $this->repository = $repository;
        $this->assign([
            'addAuth' => property_auth('propertyBillCatalogAdd'),
            'editAuth' => property_auth('propertyBillCatalogEdit'),
            'delAuth' => property_auth('propertyBillCatalogDel'),
            'detailAuth' => property_auth('propertyBillCatalogDetail'),
        ]);
    }

    /**
     *  账单目录
     * @return string|\think\response\Json
     * @throws \Exception
     *
     * @author Amos
     * 2024-01-30 10:48
     */
    public function list()
    {
        if ($this->request->isAjax()) {
            $where = $this->request->param([
                'bill_id' => '',
                'keywords' => '',
            ]);
            [$page, $limit] = $this->getPage();
            $data = $this->repository->getpropertyList($where, $page, $limit, $this->request->propertyId);
            return json()->data(['code' => 0, 'data' => $data['list'], 'count' => $data['count']]);
        }
        return $this->fetch('bill/catalog/list');
    }


    /**
     * 添加基本费用
     * @return string|\think\response\Json|\think\response\View
     * @throws \Exception
     *
     * @author Amos
     * 2024-01-30 10:48
     */
    public function addBasic()
    {
        if ($this->request->isAjax() && $this->request->get('get_type') == 'getBillCateData') {
            $where = [
                'is_show' => 1,
                'is_class' => 1,
            ];
            /** @var BillCateRepository $cateRepository */
            $cateRepository = app()->make(BillCateRepository::class);
            $cateNameData = $cateRepository->getCascaderData($where);
            return json()->data(['code' => 0, 'data' => $cateNameData]);
        } else if ($this->request->isPost()) {
            $param = $this->request->param([
                'bill_id' => '',
                'cate_id' => '',
                'amount' => '',
                'remark' => '',
                'start_date' => '',
                'end_date' => '',
            ]);
            $param['is_type'] = 1;
            validate(BillCatalogValidate::class)->scene('addBasic')->check($param);
            /** @var BillBasicRepository $billBasicrepository */
            $billBasicrepository = app()->make(BillBasicRepository::class);
            $billInfo = $billBasicrepository->get($param['bill_id']);
            if ((int)$billInfo['id'] <= 0) {
                return $this->error('账单信息错误');
            }
            $param['room_id'] = $billInfo['room_id'];
            $param['contract_id'] = $billInfo['contract_id'];
            try {
                $res = $this->repository->addBasicInfo($param, $this->request->propertyId, $this->request->userId);
                if ($res) {
                    return $this->success('添加成功');
                } else {
                    return $this->error('添加失败');
                }
            } catch (\Exception $e) {
                exception_log('添加基本费用失败', $e);
                return $this->error('网络失败');
            }
        } else {
            return $this->fetch('bill/catalog/add_basic');
        }
    }


    /**
     * 添加能源电费
     * @return string|\think\response\Json|\think\response\View
     * @throws \Exception
     *
     * @author Amos
     * 2024-01-30 10:48
     */
    public function addEnergy()
    {
        if ($this->request->isAjax() && $this->request->get('get_type') == 'getBillCateData') {
            $where = [
                'is_show' => 1,
                'is_class' => 2,
            ];
            /** @var BillCateRepository $cateRepository */
            $cateRepository = app()->make(BillCateRepository::class);
            $cateNameData = $cateRepository->getCascaderData($where);
            return json()->data(['code' => 0, 'data' => $cateNameData]);
        } else if ($this->request->isAjax() && $this->request->get('get_type') == 'getEnergyPlanData') {
            $energyType = (int)$this->request->param('energy_type');
            /** @var EnergyPlanRepository $energyPlanRepository */
            $energyPlanRepository = app()->make(EnergyPlanRepository::class);
            $list = $energyPlanRepository->search([
                'is_show' => 1,
                'property_id' => $this->request->propertyId,
                'energy_type' => $energyType ?: ''
            ], $this->request->propertyId)
                ->field('id,plan_name,mode_type,energy_type')
                ->select();
            return json()->data(['code' => 0, 'data' => $list]);
        } else if ($this->request->isAjax() && $this->request->get('get_type') == 'getEnergyPlanInfo') {
            $planId = (int)$this->request->param('plan_id');
            /** @var EnergyPlanRepository $energyPlanRepository */
            $energyPlanRepository = app()->make(EnergyPlanRepository::class);
            $planData = $energyPlanRepository->get($planId);
            return json()->data(['code' => 0, 'data' => $planData]);
        } else if ($this->request->isPost()) {
            $param = $this->request->param([
                'bill_id' => '',
                'plan_id' => '',
                'remark' => '',
                'start_date' => '',
                'end_date' => '',
                'energyBill' => [],
            ]);
            $param['is_type'] = 1;
            $energyType = (int)$param['energyBill']['energy_type'];
            $set_finance = '';
            if ($energyType == 11) {
                $set_finance = 11;
            } elseif ($energyType == 12) {
                $set_finance = 12;
            } elseif ($energyType == 13) {
                $set_finance = 13;
            } elseif ($energyType == 14) {
                $set_finance = 14;
            }

            /** @var BillCateRepository $cateRepository */
            $cateRepository = app()->make(BillCateRepository::class);
            $cateInfo = $cateRepository->search([
                'is_show' => 1,
                'is_class' => 2,
                'set_finance' => $set_finance,
            ])->field('id')->find();
            $param['cate_id'] = $cateInfo['id'];
            validate(BillCatalogValidate::class)->scene('addEnergy')->check($param);
            /** @var BillBasicRepository $billBasicRepository */
            $billBasicRepository = app()->make(BillBasicRepository::class);
            $billInfo = $billBasicRepository->get($param['bill_id']);
            if ((int)$billInfo['id'] <= 0) {
                return $this->error('账单信息错误');
            }
            $param['room_id'] = $billInfo['room_id'];
            $param['contract_id'] = $billInfo['contract_id'];
            try {
                $res = $this->repository->addEnengyInfo($param, $this->request->propertyId, $this->request->userId);
                if ($res) {
                    return $this->success('添加成功');
                } else {
                    return $this->error('添加失败');
                }
            } catch (\Exception $e) {
                exception_log('添加账单水/汽费用失败', $e);
                return $this->error('网络失败');
            }
        } else {
            /** @var EnergyMeterRepository $energyMeterRepository */
            $energyMeterRepository = app()->make(EnergyMeterRepository::class);
            $energyTypeData = $energyMeterRepository::ENERGY_TYPE;
            return $this->fetch('bill/catalog/add_energy', [
                'energyTypeData' => $energyTypeData,
            ]);
        }
    }


    /**
     * 添加账单其它费用
     * @return string|\think\response\Json|\think\response\View
     * @throws \Exception
     *
     * @author Amos
     * 2024-01-30 10:48
     */
    public function addOther()
    {
        if ($this->request->isAjax() && $this->request->get('get_type') == 'getBillCateData') {
            $where = [
                'is_show' => 1,
                'is_class' => 3,
            ];
            /** @var BillCateRepository $cateRepository */
            $cateRepository = app()->make(BillCateRepository::class);
            $cateNameData = $cateRepository->getCascaderData($where);
            return json()->data(['code' => 0, 'data' => $cateNameData]);
        } else if ($this->request->isPost()) {
            $param = $this->request->param([
                'bill_id' => '',
                'cate_id' => '',
                'amount' => '',
                'remark' => '',
                'start_date' => '',
                'end_date' => '',
            ]);
            $param['is_type'] = 1;
            validate(BillCatalogValidate::class)->scene('add')->check($param);
            /** @var BillBasicRepository $billBasicrepository */
            $billBasicrepository = app()->make(BillBasicRepository::class);
            $billInfo = $billBasicrepository->get($param['bill_id']);
            if ((int)$billInfo['id'] <= 0) {
                return $this->error('账单信息错误');
            }
            $param['room_id'] = $billInfo['room_id'];
            $param['contract_id'] = $billInfo['contract_id'];
            try {
                $res = $this->repository->addOtherInfo($param, $this->request->propertyId, $this->request->userId);
                if ($res) {
                    return $this->success('添加成功');
                } else {
                    return $this->error('添加失败');
                }
            } catch (\Exception $e) {
                exception_log('添加其它费用失败', $e);
                return $this->error('网络失败');
            }
        } else {
            return $this->fetch('bill/catalog/add_other');
        }
    }


    /**
     * 编辑账单
     * @return string|\think\response\Json|\think\response\View
     * @throws \Exception
     *
     * @author Amos
     * 2024-01-30 10:48
     */
    public function edit()
    {
        $id = (int)$this->request->param('id');
        if (!$id) {
            return $this->error('参数错误');
        }
        $info = $this->repository->getDetail($id);
        if (!$info) {
            return $this->error('信息错误');
        }
        if ($this->request->isAjax() && $this->request->get('get_type') == 'getEnergyPlanInfo') {
            $planId = (int)$this->request->param('plan_id');
            /** @var EnergyPlanRepository $energyPlanRepository */
            $energyPlanRepository = app()->make(EnergyPlanRepository::class);
            $planData = $energyPlanRepository->get($planId);
            return json()->data(['code' => 0, 'data' => $planData]);
        } else if ($this->request->isPost()) {
            $param = $this->request->param([
                'plan_id' => '',
                'remark' => '',
                'amount' => '',
                'minus_amount' => '',
                'start_date' => '',
                'end_date' => '',
                'energyBill' => [],
            ]);
            if (isset($info['energy_bill_info']) && is_array($info['energy_bill_info'])) {
                if (intval($info['energy_bill_info']['energy_type']) > 0) {
                    validate(BillCatalogValidate::class)->scene('editEnergy')->check($param);
                }
            } else {
                validate(BillCatalogValidate::class)->scene('edit')->check($param);
            }
            try {
                $res = $this->repository->editInfo($info, $param, $this->request->userId);
                if ($res) {
                    return $this->success('修改成功');
                } else {
                    return $this->error('修改失败');
                }
            } catch (\Exception $e) {
                exception_log('编辑账单明细失败', $e);
                return $this->error('网络错误');
            }
        } else {
            /** @var BillCateRepository $cateRepository */
            $cateRepository = app()->make(BillCateRepository::class);
            $cateInfo = $cateRepository->get($info['cate_id']);
            if ($cateInfo['is_class'] == 2) {
                $where = [
                    'is_show' => 1,
                    'is_class' => 2,
                ];
                $cateNameData = $cateRepository->getCascaderData($where);

                /** @var EnergyPlanRepository $energyPlanRepository */
                $energyPlanRepository = app()->make(EnergyPlanRepository::class);
                $planList = $energyPlanRepository->search([
                    'is_show' => 1,
                    'energy_type' => $info['energy_type'],
                    'property_id' => $info['property_id'],
                ], $this->request->propertyId)
                    ->field('id,plan_name,mode_type,energy_type')
                    ->select();
                /** @var EnergyPlanRepository $energyPlanRepository */
                $energyPlanRepository = app()->make(EnergyPlanRepository::class);
                $planInfo = $energyPlanRepository->get($info['plan_id']);
                /** @var EnergyMeterRepository $energyMeterRepository */
                $energyMeterRepository = app()->make(EnergyMeterRepository::class);
                $energyTypeData = $energyMeterRepository::ENERGY_TYPE;

                return $this->fetch('bill/catalog/edit_energy', [
                    'info' => $info,
                    'planInfo' => $planInfo,
                    'planList' => $planList,
                    'cateNameData' => $cateNameData,
                    'energyTypeData' => $energyTypeData,
                ]);
            } else {
                return $this->fetch('bill/catalog/edit', [
                    'info' => $info,
                ]);
            }
        }
    }

    /**
     * 账单详情
     * @return string|\think\response\Json|\think\response\View
     * @throws \Exception
     *
     * @author Amos
     * 2024-01-30 19:09
     */
    public function detail()
    {
        $id = (int)$this->request->param('catalog_id');
        if ($id <= 0) {
            return $this->error('参数错误');
        }
        $info = $this->repository->getDetail($id);
        if ($info['id'] <= 0) {
            return $this->error('信息不存在');
        }
        return $this->fetch('bill/catalog/detail', [
            'info' => $info,
        ]);
    }


    /**
     * 作废账单
     *
     * @return string|\think\response\Json|\think\response\View
     *
     * @author Amos
     * 2024-03-15 10:58
     */
    public function invalidAdd()
    {
        $ids = (array)$this->request->param('ids');
        $remark = $this->request->param('remark', '');
        try {
            $data = $this->repository->batchInvalidBillCatalog($ids, $this->request->userId, $remark);
            if ($data) {
                return $this->success('作废成功');
            } else {
                return $this->error('作废失败');
            }
        } catch (\Exception $e) {
            exception_log('作废账单失败', $e);
            return $this->error('网络错误');
        }
    }

    /**
     * 收入 待支付明细
     * @return string|\think\response\Json
     * @throws \Exception
     *
     * @author Amos
     * 2024-05-07 18:01
     */
    public function stayPayBasicList()
    {
        if ($this->request->isAjax()) {
            $where = $this->request->param([
                'contract_id' => '',
                'month_time' => '',
                'keywords' => '',
            ]);
            $where['is_type'] = 1;
            $where['status'] = [2, 5, 8];
            [$page, $limit] = $this->getPage();
            $res = $this->repository->getpropertyList($where, $page, $limit, $this->request->propertyId);
            return json()->data(['code' => 0, 'data' => $res['list'], 'count' => $res['count']]);
        }
        /** @var BillCateRepository $cateRepository */
        $cateRepository = app()->make(BillCateRepository::class);
        $cateNameData = $cateRepository->getCascaderData(['is_show' => 1]);
        return $this->fetch('bill/basic/stay_pay_catalog_list', [
            'cateNameData' => $cateNameData,
            'paymentAuth' => property_auth('propertyBillCatalogPaymentSubmit'),
            'invalidAuth' => property_auth('propertyBillCatalogInvalidSubmit'),
        ]);
    }


    /**
     * 支出 待支付明细
     * @return string|\think\response\Json
     * @throws \Exception
     *
     * @author Amos
     * 2024-05-07 18:01
     */
    public function stayPayExpendList()
    {
        if ($this->request->isAjax()) {
            $where = $this->request->param([
                'contract_id' => '',
                'month_time' => '',
                'keywords' => '',
            ]);
            $where['is_type'] = 2;
            $where['status'] = [2, 8];
            [$page, $limit] = $this->getPage();
            $res = $this->repository->getpropertyList($where, $page, $limit, $this->request->propertyId);
            return json()->data(['code' => 0, 'data' => $res['list'], 'count' => $res['count']]);
        }
        /** @var BillCateRepository $cateRepository */
        $cateRepository = app()->make(BillCateRepository::class);
        $cateNameData = $cateRepository->getCascaderData(['is_show' => 1]);
        return $this->fetch('bill/expend/stay_pay_catalog_list', [
            'cateNameData' => $cateNameData,
            'paymentAuth' => property_auth('propertyBillCatalogPaymentSubmit'),
            'invalidAuth' => property_auth('propertyBillCatalogInvalidSubmit'),
        ]);
    }


    /**
     * 账单支付
     * @return string|\think\response\Json|\think\response\View
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     *
     * @author Amos
     * 2024-03-15 21:02
     */
    public function paymentAdd()
    {
        if ($this->request->isPost()) {
            $param = $this->request->param([
                'id' => '',
                'remark' => '',
                'picture' => '',
                'pay_amount' => '',
                'pay_method' => '',
            ]);
            validate(BillCatalogValidate::class)->scene('payment')->check($param);
            $ids = array_filter(explode(',', $param['id']));
            $num = 0;
            foreach ($ids as $v) {
                $info = $this->repository->get($v);
                if (isset($info) && $info['id'] > 0 && ($info['status'] == 2 || $info['status'] == 5 || $info['status'] == 8)) {
                    $res = $this->repository->paymentBill($info, $param, $this->request->userId);
                    if ($res) {
                        $num++;
                    }
                }
            }
            if ($num) {
                return $this->success('成功支付 ' . $num . ' 份账单');
            } else {
                return $this->error('账单支付失败');
            }
        } else {
            $id = $this->request->param('id');
            $ids = array_filter(explode(',', $id));
            $stayPaylist = $this->repository->getSearch([])
                ->where('id', 'in', $ids)
                ->where('status', 'in', '2,5,8')
                ->with([
                    'billBasicInfo' => function ($query) {
                        $query->bind(['number']);
                    },
                    'cateInfo' => function ($query) {
                        $query->bind(['cate_name']);
                    },
                    'userInfo' => function ($query) {
                        $query->field('id,username,mobile');
                        $query->bind(['username' => 'username', 'mobile' => 'mobile']);
                    },
                ])
                ->field('id,status,cate_id,user_id,bill_id,total_amount')
                ->append(['stay_pay_amount'])
                ->select()->toArray();
            $stayPayoney = array_sum(get_arr_column($stayPaylist, 'stay_pay_amount'));
            if ($stayPayoney <= 0) {
                return $this->error('该订单己支付完毕，禁止重复操作');
            }
            $this->assign([
                'repairData' => $stayPaylist,
                'stayPayoney' => $stayPayoney,
            ]);
            return $this->fetch('bill/catalog/payment_add');
        }
    }


    /**
     *  自定义支付
     * @return string|\think\response\Json|\think\response\View
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     *
     * @author Amos
     * 2024-05-30 08:12
     */
    public function paymentCustomAdd()
    {
        $id = $this->request->param('id');
        if (!$id) {
            return $this->error('参数错误');
        }
        $info = $this->repository->get($id);
        if (!$info) {
            return $this->error('信息错误');
        }
        if ($this->request->isPost()) {
            $param = $this->request->param([
                'id' => '',
                'remark' => '',
                'picture' => '',
                'pay_amount' => '',
                'pay_method' => '',
            ]);
            validate(BillCatalogValidate::class)->scene('payment')->check($param);
            if ($param['pay_amount'] > $info['stay_pay_amount']) {
                return $this->error('支付金额大于待支付金额');
            }
            if (isset($info) && $info['id'] > 0 && ($info['status'] == 2 || $info['status'] == 5 || $info['status'] == 8)) {
                $res = $this->repository->paymentCustomBill($info, $param, $this->request->userId);
                if ($res) {
                    return $this->success('支付成功');
                } else {
                    return $this->error('账单支付失败');
                }
            } else {
                return $this->error('账单己支付或未审核');
            }
        } else {
            if ($info['stay_pay_amount'] <= 0) {
                return $this->error('该订单己支付完毕，禁止重复操作');
            }
            $this->assign([
                'stayPayoney' => $info['stay_pay_amount'],
            ]);
            return $this->fetch('bill/catalog/payment_add_custom');
        }
    }


    /**
     * 删除账单
     * @return string|\think\response\Json|\think\response\View
     *
     * @author Amos
     * 2024-01-30 10:47
     */
    public function del()
    {
        $ids = (array)$this->request->param('ids');
        try {
            $data = $this->repository->batchDelete($ids, $this->request->userId);
            if ($data) {
                return $this->success('删除成功');
            } else {
                return $this->error('删除失败');
            }
        } catch (\Exception $e) {
            exception_log('删除账单明细失败', $e);
            return $this->error('网络失败');
        }
    }

}